#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# bulid.py

import os, sys, time , argparse
from biplist import *
from pbxproj import XcodeProject 
from git import Git
import requests
from ipaparse import *
from dingtalk import DingTalk

validate_count = 0

class XcodeActive:
    def __init__(self, config):
        start_time = time.time()
        self.config = config
        self.setupConfig()
        self.activePre()
        self.active()
        self.uplaod()
        end_time = time.time()
        since_time =  (end_time-start_time)/60
        print("打包结束 耗时 %s 分钟",since_time)
        self.cleanBulid()

    def cleanBulid(self):
         print("****************************** 开始清除 bulid ******************************")
         print("****************************** 清除 bulid 结束 ******************************")

    def activePre(self):
        print("****************************** 准备编译 ******************************")
        print("projectPath ----->" ,self.project_root)
        os.chdir(self.project_root)
        r = Git(self.project_root)
        r.checkout("master")
        r.pull()
        self.commit_log = r.log('--pretty=%s',
                              max_count=10,
                              date='format:%Y-%m-%d %H:%M')
        print(self.commit_log)
        # command_pod = "pod update --verbose --no-repo-update"
        # self.sys_command(command_pod)
        self.setup_xcode_config()

        print("****************************** 准备编译结束 ******************************")


    def setup_xcode_config(self):
        project_path = self.project_root + "/%s.xcodeproj/project.pbxproj" % (self.project_name)
        print("project_path ---->",project_path)
        project = XcodeProject.load(project_path)
        # print("project   -----> ",project)

        target = project.get_target_by_name(self.scheme)
        # print("target is -----> ", target)
        configuelist = target["buildConfigurationList"]
        print("configuelist ---> ",configuelist)
        objects = project["objects"]
        buildConfigurations = objects[configuelist]["buildConfigurations"]
        print("buildConfigurations --->",buildConfigurations)
        for key in buildConfigurations:
            if objects[key]["buildSettings"]:
                buildSettings = objects[key]["buildSettings"]
                print("buildConfigurations --->",buildSettings)
                buildSettings['MARKETING_VERSION'] = self.version
                buildSettings['CURRENT_PROJECT_VERSION'] = self.build
        
        if self.noti_extension != None:
            target = project.get_target_by_name(self.noti_extension)
            configuelist = target["buildConfigurationList"]
            objects = project["objects"]
            buildConfigurations = objects[configuelist]["buildConfigurations"]
            for key in buildConfigurations:
                if objects[key]["buildSettings"]:
                    buildSettings = objects[key]["buildSettings"]
                    buildSettings['MARKETING_VERSION'] = self.version
                    buildSettings['CURRENT_PROJECT_VERSION'] = self.build
        project.save()
        
    def active(self):
        print("****************************** 开始编译 ******************************")
        rootPath = os.path.dirname(__file__)
        os.chdir(rootPath)
        command = "xcodebuild -workspace %s/%s.xcworkspace archive -scheme %s -configuration %s -archivePath %s"  % (
    self.project_root, self.project_name, self.scheme, self.config,self.active_filepath)
        self.sys_command(command)
        command = "xcodebuild -exportArchive -archivePath %s -exportOptionsPlist %s -exportPath %s -allowProvisioningUpdates" % (
    self.active_filepath, self.export_plist, self.build_filepath)
        self.sys_command(command)
    
    def uplaod(self):
        if self.config == "Test":
            if self.pgyer != None:
                self.uplaod_pgyer()
                return
            if self.fir != None:
                print("upload fir.im")
                self.upload_fir()
                return
        elif self.config == "Pre":
            if self.pgyer != None:
                self.uplaod_pgyer()
                return
            if self.fir != None:
                print("upload fir.im")
                self.upload_fir()
                return
        else:
            self.uploadAppStore()
            
    def uplaod_pgyer(self):
        ipa_path = "%s/%s.ipa" %(self.build_filepath,self.scheme)
        url = 'https://www.pgyer.com/apiv2/app/upload'
        if self.commit_log != None:
            self.pgyer["buildUpdateDescription"] = self.commit_log
        files = open(ipa_path,"rb")
        r = requests.post(url,data=self.pgyer,files=files)
        print(r.json)

    def upload_fir(self):
        ipa_path = "%s/%s.ipa" %(self.build_filepath,self.scheme)
        ipainfo = ipaparse(ipa_path)
        url = 'http://api.bq04.com/apps'
        print(self.fir)
        data = {"api_token":self.fir["api_token"],"bundle_id":self.fir["bundle_id"],"type":"ios"}
        # r = requests.post(url,data=data)
        # print(r.json())
        dic = self.post(url,data,None,1)
        upload_url = dic["cert"]["binary"]["upload_url"]
        key = dic["cert"]["binary"]["key"]
        token = dic["cert"]["binary"]["token"]
        icon_key = dic["cert"]["icon"]["key"]
        icon_token = dic["cert"]["icon"]["token"]
        icon_url =  dic["cert"]["icon"]["upload_url"]
        icon_files = {"file":ipainfo.img_file}
        download_url =  'http://%s/%s' % (dic['download_domain'],dic['short'])
        # r = requests.post(icon_url,data={"token":icon_token,"key":icon_key},files=icon_files)
        json = self.post(icon_url,{"token":icon_token,"key":icon_key},icon_files,1)
        print(json)
        
        files = {"file":open(ipa_path,"rb")}
        changelog = ""
        if self.commit_log is not None:
            changelog = self.commit_log
        data = {"key":key,"token":token,"x:name":ipainfo.app_name,"x:version":ipainfo.app_version,"x:build":ipainfo.app_build,"x:release_type":"Adhoc","x:changelog":changelog}
        # r = requests.post(upload_url,data=data,files=files)
        json = self.post(upload_url,data,files,1)

        print(json)
        
        info = {}
        info["buildName"] = ipainfo.app_name
        info["buildVersion"] = self.version
        info["buildVersionNo"] = self.build
        info["buildUpdateDescription"] = changelog
        info["download_url"] = download_url
        ding = DingTalk()
        
        ding.sendInfo(info)
    
    def post(self,url,data,files,retry):
        try:
            if files != None:
                r = requests.post(url,data=data,files=files)
                return r.json()
            else:
                r = requests.post(url,data=data)
                return r.json()
        except requests.exceptions.RequestException as e:
            if retry == 1:
                self.post(url,data,files,0)
            else:
                print(str(e))
                sys.exit(0)

    def uploadAppStore(self):
        print("********************************* connect appStore validate ***********************************")
        api_key = self.api_key
        issuer_id = self.issuer_id
        ipa_path = "%s/%s.ipa" %(self.build_filepath,self.scheme)
        ipainfo = ipaparse(ipa_path)
        r1 = os.system('xcrun altool --validate-app -f %s -t ios --apiKey %s --apiIssuer %s --verbose'%(ipa_path, api_key,issuer_id))
        if r1 == 0:
            print('*********************************** upload ipa to appstore ***********************************')
            command = 'xcrun altool --upload-app -f %s -t ios --apiKey %s --apiIssuer %s --verbose'%(ipa_path, api_key,issuer_id)
            self.sys_command(command)
            # dingTalk = DingTalk()
            # info = {"buildName":"小熊美术","buildVersion":archiveConfigue.cAppVersion,"buildVersionNo":archiveConfigue.cBuildVersion}
            # dingTalk.sendInfoWithAppStore(info)
            print('*********************************** upload success ***********************************')
        else:
            global validate_count
            validate_count += 1
            if validate_count < 3:
                self.uploadAppstore()
            else:
                print('********* 验证失败、请重新打包 ***************')
                validate_count = 0
                sys.exit(0)
        
    def setupConfig(self):
        self.appstore_appkey = None
        self.appstore_apiIssuer = None
        self.develop_email = None
        self.develop_password = None
        
        rootPath = os.path.dirname(__file__)
        os.chdir(rootPath)
        print("rootPath ---> " + rootPath)
        try:
            plistPath = os.path.abspath("../bulid/config/project.plist")
            print("plistPath ---> " + plistPath)
            plist = readPlist(plistPath)
            print(plist)
            self.version = plist["appVersion"]
            self.build = plist["buildVersion"]
            self.project_name = plist["projectName"]
            self.scheme = plist["targetName"]
            self.project_root = plist["path"]
            self.teamid = plist["teamid"]
            self.uploadDes = plist["uploadDes"]
            self.active_path = rootPath + "/active"
            self.active_filepath = "%s/%s-%s.xcarchive" % (self.active_path, self.scheme,self.build)
            self.build_path = rootPath + "/export"
            self.build_filepath = "%s/%s-%s" % (self.build_path, self.scheme,self.build)
            self.noti_extension = None
            if plist["notification"] != None:
               self.noti_extension = plist["notification"]
            self.create_dir()
            
            self.setup_pgyer_info(plist)
            print(self.pgyer)
            self.setup_fir_info(plist)
            self.setup_appstore_info(plist)
            if "Release" == self.config:
                self.export_plist = rootPath + "/config/releaseExport.plist"
            else:
                self.export_plist = rootPath + "/config/debugExport.plist"

        except (InvalidPlistException , NotBinaryPlistException) as e:
            print ("Something bad happened:",e)
            sys.exit(0)

    def setup_pgyer_info(self,plist):
        self.pgyer = None
        pgyerConfig = plist["pgyer"]
        if pgyerConfig["api_key"] != "":
            temp = {}
            temp["_api_key"] = pgyerConfig["api_key"]
            temp["buildInstallType"] = pgyerConfig["buildInstallType"]
            if pgyerConfig["buildInstallType"] == "2":
                temp["buildPassword"] = pgyerConfig["password"]
            self.pgyer = temp

    def setup_fir_info(self,plist):
        self.fir = None
        firConfig = plist["fir"]
        if firConfig["api_token"] != None:
            temp = {"api_token":firConfig["api_token"]}
            temp["bundle_id"] = firConfig["bundle_id"]
            temp["type"] = "ios"
            temp["url"] = firConfig["url"]
            self.fir = temp
            
    def setup_appstore_info(self,plist):
        appConfig = plist["appstore"]
        self.api_key = appConfig["api_key"]
        self.issuer_id = appConfig["issuer_id"]
        
    def create_dir(self):
        if os.path.exists(self.active_path) == False:
            os.mkdir(self.active_path)
            os.mkdir(self.build_path)

    def sys_command(self,command):
        status = os.system(command)
        if status != 0:
            print("Error: ",command)
            sys.exit(0)
    